"""
logic={'ondatatype':'data',"and":{"a":{">":1,"<":5,'local':["k1m"]},"b":{">":6,"<=":9}}}
"""
import pandas as pd
logic_f=["and","or", ">",">=","=","!=","<","<=","in"]
check_calc={"=":"__eq__","<":"__lt__","<=":"__le__",">":"__gt__",">=":"__ge__","!=":"__ne__"}
check_calc1={"and":"__and__","or":"__or__","in":"__ini__"}
check_calc2={"and":"__and__","or":"__or__"}
def check_logic(dd,check_flag,v1):
    rr0=False
    if type(dd)==type(v1):
        rr0 = getattr(dd, check_flag)(v1)
    else:
        try:
            v1=type(dd)(v1)
            rr0 = getattr(dd, check_flag)(v1)
        except Exception as e:
            print("error","check_logic",e)
    return rr0
def check_logic_byflag(dd,flag,vv):
    flag0=check_calc[flag]
    r=check_logic(dd,flag0,vv)
    return r
def get_value_byfelid(data,k):
    data0 = data
    if k in data.keys():
        dd = data0[k]
    else:
        if "." in k:
            for i in k.split("."):
                if i not in data0.keys():
                    return None
                else:
                    data0 = data0[i]
            dd = data0
        else:
            dd = None
    return dd
def logic_calc(logic,data,pre=""):
    if not logic:
        return True
    if isinstance(data,dict):
        r= logic_calc_dict(logic,data,pre)
    else:
        if pre=="":
            pre="and"
        r=logic_calc_df(logic, data, ukey=pre)
    return r
def logic_calc_dict_old(logic,data,pre=""):
    r = None
    r1 = True
    for k,v in logic.items():
        # print(k, v)
        if k in logic_f:
            r1=logic_calc_dict(v,data,pre=k)
        else:
            r1=True
            dd=get_value_byfelid(data,k)
            for k1,v1 in v.items():
                check_flag=check_calc[k1]
                # dd=get_value_byfelid(data,k)
                if pd.isna(dd):
                    rr0 = False
                else:
                    if isinstance(v1,str):
                        if "." in v1:
                            l0=v1.split(".")
                            v1=data
                            for i in l0:
                                if i in v1.keys():
                                    v1 = v1[i]
                        else:
                            if v1 in data.keys():
                                v1=data[v1]
                    rr0=check_logic(dd,check_flag,v1)
                # if rr0:
                #     print("1")
                r1=r1.__and__(bool(rr0))
                # print(k,dd,k1,v1,rr0,r1)
        check_flag1 = check_calc1.get(pre, "__and__")
        if r is not None:
            r = check_logic(dd,check_flag1,v1)
        else:
            r=r1
    return r
def logic_calc_dict(logic,data,pre=""):
    r = None
    for k,v in logic.items():
        # print(k, v)
        if k in logic_f:
            r1=logic_calc_dict(v,data,pre=k)
        else:
            r1=True
            dd=get_value_byfelid(data,k)
            for k1,v1 in v.items():
                check_flag=check_calc[k1]
                if pd.isna(dd):
                    if pd.isna(v1):
                        rr0 = True
                    else:
                        rr0 = False
                else:
                    if isinstance(v1,str):
                        if v1[0]==":":
                            v1=v1[1:]
                            rr0 = check_logic(dd, check_flag, v1)
                        else:
                            if "." in v1:
                                l0=v1.split(".")
                                v1=data
                                for i in l0:
                                    if i in v1.keys():
                                        v1 = v1[i]
                            else:
                                if v1 in data.keys():
                                    v1=data[v1]
                            if pd.isna(dd):
                                if pd.isna(v1):
                                    rr0 = True
                                else:
                                    rr0 = False
                            else:
                                if pd.isna(v1):
                                    rr0 = False
                                    # print(k,v,dd,v1,data)
                                else:
                                    rr0=check_logic(dd,check_flag,v1)
                    elif isinstance(v1,bytes):
                        v1=v1.decode()
                        rr0 = check_logic(dd, check_flag, v1)
                    # elif isinstance(v1,list):
                    #     for vv1 in
                    else:
                        rr0 = check_logic(dd, check_flag, v1)
                r1=r1.__and__(bool(rr0))
        check_flag1 = check_calc1.get(pre, "__and__")
        if r is None:
            r=r1
        else:
            r = check_logic(r,check_flag1,r1)
    return r

def logic_calc_dict_multistep(logic,data,pre=""):
    r = None
    for k,v in logic.items():
        r1=True
        dd=get_value_byfelid(data,k)
        for k1,v1 in v.items():
            check_flag=check_calc[k1]
            indexs = (0, v1)
            if pd.isna(dd):
                if isinstance(v1,str):
                    rr0 = False
                elif isinstance(v1,bytes):
                    rr0 = False
                elif isinstance(v1,list):
                    rr0 = False
                else:
                    if pd.isna(v1):
                        rr0 = True
                    else:
                        rr0 = False
            else:
                if isinstance(v1,str):
                    if v1[0]==":":
                        v1=v1[1:]
                        rr0 = check_logic(dd, check_flag, v1)
                    else:
                        if "." in v1:
                            l0=v1.split(".")
                            v1=data
                            for i in l0:
                                if i in v1.keys():
                                    v1 = v1[i]
                        else:
                            if v1 in data.keys():
                                v1=data[v1]
                        if pd.isna(dd):
                            if pd.isna(v1):
                                rr0 = True
                            else:
                                rr0 = False
                        else:
                            if pd.isna(v1):
                                rr0 = False
                                # print(k,v,dd,v1,data)
                            else:
                                rr0=check_logic(dd,check_flag,v1)
                elif isinstance(v1,bytes):
                    v1=v1.decode()
                    rr0 = check_logic(dd, check_flag, v1)
                elif isinstance(v1,list):
                    nn0=0
                    rr0=False
                    for vv1 in v1:
                        rr1 = check_logic(dd, check_flag, vv1)
                        if not rr1:
                            break
                        indexs = (nn0, vv1)
                        nn0=nn0+1
                        rr0=rr1
                else:
                    rr0 = check_logic(dd, check_flag, v1)
            r1=r1.__and__(bool(rr0))
        check_flag1 = check_calc1.get(pre, "__and__")
        if r is None:
            r=r1
        else:
            r = check_logic(r,check_flag1,r1)
    return r,indexs
"""
对dataframe逻辑操作：
1.支持sortr:排序后的百分比；暂时不支持groupby  sort必须写在最前面
2.正常的大小操作   & |
最红返回过滤后数据集么？还是逻辑结果？逻辑结果吧，加入sort:数据集
"""
logic_df=["or", ">",">=","=","!=","<","<="]
def logic_calc_df(logic,data,ukey="and",out=None,out_value=[False,True]):
    r = data.copy()
    dds=[]
    for k,v in logic.items():
        if k in ["or"]:
            r=logic_calc_df(v,r,k)
        else:
            if k in r.columns:
                dd=r[k]
                for k1,v1 in v.items():
                    if k1=="sort":
                        rr=r.sort_values(k)
                        rr=rr.copy()
                        # rr.dropna(axis=0,inplace=True)
                        n0=int(v1[0]*len(rr))
                        n1=int(v1[1]*len(rr))
                        r=rr[n0:n1]
                        dd = r[k]
                    # elif k1=="in":
                    #     r = r[r[k] in v1]
                    #     dd = r[k]
                    else:
                        if isinstance(v1,str):
                            if v1[0]==":":
                                v1=v1[1:]
                                vd = v1
                            else:
                                if v1  in r.columns:
                                    vd=r[v1]
                                else:
                                    vd=v1
                        elif isinstance(v1,bytes):
                            vd=v1.decode()
                        else:
                            vd=v1
                        check_flag=check_calc[k1]
                        rr0 = getattr(dd, check_flag)(vd)
                        dds.append(rr0)
    if dds:
        dd=dds[0]
        for i in dds[1:]:
            if ukey=="and":
                dd = dd & i
            else:
                dd=dd|i
        if out   is None:
            r=r[dd]
            r=r.copy()
        else:
            r[out]=out_value[0]
            r.loc[dd,out]=out_value[1]
    return r

if __name__ == '__main__':
    """
    1.符合逻辑 and or in 
    2.key为字段  且为可以通过. 寻址多级字典
    3.value可以是值，可以为字段  且为可以通过. 寻址多级字典
    4.支持逻辑关系："=":"__eq__","<":"__lt__","<=":"__le__",">":"__gt__",">=":"__ge__","!=":"__ne__"
    
    混淆概念疑问：
    数据不存在  则为None,None是否必要？跟None数据的混淆怎么解决？——>增加模式可以解决
    value 的值为str时，跟字段模式混淆怎么解决？——>
    
    """
    a = [{"a": 1, "b": 2}, {"a": 2, "b": 1}, {"a": 3, "b": 4}]
    # import pandas as pd
    # a=pd.DataFrame(a)
    # print("a>1",logic_calc({"a":{">":1}},a))
    # print("a>=1", logic_calc({"a": {">=": 1}}, a))
    # print("a<1", logic_calc({"a": {"<": 1}}, a))
    # print("sort0", logic_calc({"a": {"sort": [0,0.4]}}, a))
    # print("a>1<3", logic_calc({"a": {">": 1,"<":3}}, a))
    # print("a>1,b>1", logic_calc({"a": {">": 1},"b":{">":1}}, a))
    # print("a>2 or b>1", logic_calc({"or":{"a": {">": 2}, "b": {">": 1}}}, a))
    #
    # b={"test_f":{"a":3},"cc":{"d":2},"v":10,"c":2,"d":3}
    # print("s00",logic_calc({"c":{"<=":2}},b))
    # print("s01", logic_calc({"c": {"<": 2}}, b))
    # print("s02", logic_calc({"c": {">=": 2}}, b))
    # print("s03", logic_calc({"c": {">": 2}}, b))
    #
    # print("s10",logic_calc({"c":{"<=":"cc.d"}},b))
    # print("s11", logic_calc({"c": {"<": "cc.d"}}, b))
    # print("s12", logic_calc({"c": {">=": "cc.d"}}, b))
    # print("s13", logic_calc({"c": {">": "cc.d"}}, b))
    #
    # print("s20",logic_calc({"c":{"<=":"c"}},b))
    # print("s21", logic_calc({"c": {"<": "c"}}, b))
    # print("s22", logic_calc({"c": {">=": "c"}}, b))
    # print("s23", logic_calc({"c": {">": "c"}}, b))
    #
    # print("s30",logic_calc({"cc.d":{"<=":2}},b))
    # print("s31", logic_calc({"cc.d": {"<": 2}}, b))
    # print("s32", logic_calc({"cc.d": {">=": 2}}, b))
    # print("s33", logic_calc({"cc.d": {">": 2}}, b))
    #
    # print("s40",logic_calc({"cc.d":{"<=":"cc.d"}},b))
    # print("s41", logic_calc({"cc.d": {"<": "cc.d"}}, b))
    # print("s42", logic_calc({"cc.d": {">=": "cc.d"}}, b))
    # print("s43", logic_calc({"cc.d": {">": "cc.d"}}, b))

    # print(logic_calc({"and": {"test_f.a": {">": 1}, "test_f.a": {"<=": 10000}}},b))
    # # print(logic_calc({"and": {"test_f.a": {">": "test_f.b","<=": 10000}}}, b))
    # # print(logic_calc({"and": {"v": {">": 1}, "v": {"<=": 10000}}}, b))
    # print(logic_calc({"and": {"test_f.a": {">": "cc.d", "<=": 10000}}}, b))
    # print(logic_calc({"test_f.a": {">": "v", "<=": 10000}}, b))
    for b in a:
        print(b,logic_calc({"a": {">": 2},"b":{"=":1}}, b))
